<template>
  <div class="mobile-upload" :class="{ 'is-disabled': disabled }">
    <div class="upload-list" v-if="fileList.length > 0">
      <div v-for="(file, index) in fileList" :key="index" class="upload-item">
        <div class="upload-thumbnail" :style="getThumbnailStyle(file)">
          <div v-if="file.status === 'loading'" class="upload-loading">
            <div class="loading-spinner"></div>
          </div>
          <div v-else-if="file.status === 'error'" class="upload-error">
            <i class="fas fa-exclamation-circle"></i>
          </div>
        </div>
        <div class="upload-actions">
          <i class="fas fa-times-circle" @click="handleRemove(index)"></i>
        </div>
      </div>
    </div>
    
    <div class="upload-trigger" v-if="fileList.length < maxCount" @click="handleTriggerClick">
      <input
        ref="fileInput"
        type="file"
        class="file-input"
        :accept="accept"
        :multiple="multiple"
        :disabled="disabled"
        @change="handleFileChange"
      >
      <div class="upload-icon">
        <i class="fas fa-camera"></i>
      </div>
      <div class="upload-text">{{ uploadText }}</div>
    </div>
    
    <!-- 移动端特有的上传选择弹窗 -->
    <div class="upload-popup" v-if="showPopup" @click="closePopup">
      <div class="popup-content" @click.stop>
        <div class="popup-title">选择上传方式</div>
        <div class="popup-options">
          <div class="popup-option" @click="selectFile('camera')">
            <i class="fas fa-camera"></i>
            <span>拍照</span>
          </div>
          <div class="popup-option" @click="selectFile('album')">
            <i class="fas fa-images"></i>
            <span>从相册选择</span>
          </div>
        </div>
        <div class="popup-cancel" @click="closePopup">取消</div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'MobileUpload',
  props: {
    value: {
      type: Array,
      default: () => []
    },
    maxCount: {
      type: Number,
      default: 9
    },
    maxSize: {
      type: Number,
      default: 10 // MB
    },
    accept: {
      type: String,
      default: 'image/*'
    },
    multiple: {
      type: Boolean,
      default: false
    },
    disabled: {
      type: Boolean,
      default: false
    },
    uploadText: {
      type: String,
      default: '上传图片'
    },
    compress: {
      type: Boolean,
      default: true
    },
    quality: {
      type: Number,
      default: 0.8 // 图片压缩质量
    }
  },
  data() {
    return {
      fileList: this.value.map(item => ({
        ...item,
        status: 'done'
      })),
      showPopup: false
    }
  },
  watch: {
    value: {
      handler(val) {
        this.fileList = val.map(item => ({
          ...item,
          status: item.status || 'done'
        }))
      },
      deep: true
    }
  },
  methods: {
    handleTriggerClick() {
      if (this.disabled) return
      
      // 在移动设备上展示弹窗选择上传方式
      if (this.isMobileDevice()) {
        this.showPopup = true
      } else {
        // 桌面设备直接调用文件选择器
        this.$refs.fileInput.click()
      }
    },
    
    closePopup() {
      this.showPopup = false
    },
    
    selectFile(source) {
      this.closePopup()
      
      if (source === 'camera') {
        // 设置接受类型为相机
        this.$refs.fileInput.setAttribute('capture', 'environment')
      } else {
        // 移除capture属性，允许从相册选择
        this.$refs.fileInput.removeAttribute('capture')
      }
      
      this.$refs.fileInput.click()
    },
    
    handleFileChange(e) {
      const files = e.target.files
      if (!files.length) return
      
      // 清空input，以便同一文件可以重复选择
      e.target.value = ''
      
      // 处理文件
      Array.from(files).forEach(file => {
        if (this.validateFile(file)) {
          this.addFile(file)
        }
      })
    },
    
    validateFile(file) {
      // 文件大小验证（MB转字节）
      const isValidSize = file.size <= this.maxSize * 1024 * 1024
      
      if (!isValidSize) {
        this.$emit('error', {
          message: `文件大小不能超过 ${this.maxSize}MB`,
          file
        })
        return false
      }
      
      return true
    },
    
    async addFile(file) {
      // 创建缩略图
      const thumbnail = await this.createThumbnail(file)
      
      // 压缩文件（如果需要）
      let processedFile = file
      if (this.compress && file.type.includes('image')) {
        try {
          processedFile = await this.compressImage(file)
        } catch (error) {
          console.error('Image compression failed:', error)
        }
      }
      
      // 添加文件到列表
      const newFile = {
        file: processedFile,
        url: thumbnail,
        name: file.name,
        status: 'done',
        size: processedFile.size
      }
      
      const newFileList = [...this.fileList, newFile]
      this.fileList = newFileList
      this.$emit('input', newFileList)
      this.$emit('change', newFileList)
    },
    
    handleRemove(index) {
      const newFileList = [...this.fileList]
      newFileList.splice(index, 1)
      this.fileList = newFileList
      this.$emit('input', newFileList)
      this.$emit('change', newFileList)
    },
    
    getThumbnailStyle(file) {
      if (file.url) {
        return { backgroundImage: `url(${file.url})` }
      }
      return {}
    },
    
    // 创建图片缩略图
    createThumbnail(file) {
      return new Promise((resolve) => {
        if (!file.type.includes('image')) {
          // 非图片文件使用默认图标
          resolve('')
          return
        }
        
        const reader = new FileReader()
        reader.onload = (e) => {
          resolve(e.target.result)
        }
        reader.readAsDataURL(file)
      })
    },
    
    // 压缩图片
    compressImage(file) {
      return new Promise((resolve, reject) => {
        const reader = new FileReader()
        reader.onload = (e) => {
          const img = new Image()
          img.onload = () => {
            // 创建canvas
            const canvas = document.createElement('canvas')
            let width = img.width
            let height = img.height
            
            // 限制最大尺寸
            const maxDimension = 1920
            if (width > maxDimension || height > maxDimension) {
              if (width > height) {
                height = Math.floor(height * (maxDimension / width))
                width = maxDimension
              } else {
                width = Math.floor(width * (maxDimension / height))
                height = maxDimension
              }
            }
            
            canvas.width = width
            canvas.height = height
            
            // 绘制图像
            const ctx = canvas.getContext('2d')
            ctx.drawImage(img, 0, 0, width, height)
            
            // 转换为blob
            canvas.toBlob(
              (blob) => {
                if (!blob) {
                  reject(new Error('Canvas to Blob conversion failed'))
                  return
                }
                
                // 创建一个新文件对象
                const compressedFile = new File([blob], file.name, {
                  type: file.type,
                  lastModified: Date.now()
                })
                
                resolve(compressedFile)
              },
              file.type,
              this.quality
            )
          }
          
          img.onerror = () => {
            reject(new Error('Image loading failed'))
          }
          
          img.src = e.target.result
        }
        
        reader.onerror = () => {
          reject(new Error('FileReader failed'))
        }
        
        reader.readAsDataURL(file)
      })
    },
    
    // 检测是否为移动设备
    isMobileDevice() {
      return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
    }
  }
}
</script>

<style scoped>
.mobile-upload {
  position: relative;
}

.upload-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 8px;
}

.upload-item {
  position: relative;
  width: 80px;
  height: 80px;
  border-radius: var(--border-radius-sm);
  overflow: hidden;
}

.upload-thumbnail {
  width: 100%;
  height: 100%;
  background-color: #f5f5f5;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  border: 1px solid #f0f0f0;
  border-radius: var(--border-radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
}

.upload-actions {
  position: absolute;
  top: 0;
  right: 0;
  padding: 4px;
  z-index: 1;
}

.upload-actions i {
  color: rgba(0, 0, 0, 0.6);
  background: rgba(255, 255, 255, 0.8);
  border-radius: 50%;
  font-size: 18px;
  cursor: pointer;
}

.upload-loading {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(255, 255, 255, 0.7);
  display: flex;
  align-items: center;
  justify-content: center;
}

.loading-spinner {
  width: 24px;
  height: 24px;
  border: 2px solid rgba(0, 0, 0, 0.1);
  border-top-color: #1890ff;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.upload-error {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(255, 0, 0, 0.1);
  display: flex;
  align-items: center;
  justify-content: center;
}

.upload-error i {
  color: #ff4d4f;
  font-size: 24px;
}

.upload-trigger {
  width: 80px;
  height: 80px;
  border: 1px dashed #d9d9d9;
  border-radius: var(--border-radius-sm);
  background-color: #fafafa;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all 0.3s;
}

.upload-trigger:hover, .upload-trigger:active {
  border-color: #1890ff;
}

.file-input {
  display: none;
}

.upload-icon {
  font-size: 20px;
  color: #999;
  margin-bottom: 4px;
}

.upload-text {
  font-size: 12px;
  color: #999;
}

.is-disabled .upload-trigger {
  background-color: #f5f5f5;
  border-color: #d9d9d9;
  cursor: not-allowed;
  color: #bfbfbf;
}

.is-disabled .upload-icon,
.is-disabled .upload-text {
  color: #bfbfbf;
}

/* 移动端上传弹窗 */
.upload-popup {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 1000;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.popup-content {
  width: 100%;
  background-color: white;
  border-top-left-radius: 12px;
  border-top-right-radius: 12px;
  overflow: hidden;
}

.popup-title {
  text-align: center;
  padding: 16px;
  font-size: var(--font-size-md);
  color: #333;
  border-bottom: 1px solid #f0f0f0;
}

.popup-options {
  display: flex;
  padding: 20px 16px;
  justify-content: space-around;
}

.popup-option {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}

.popup-option i {
  font-size: 24px;
  color: #1890ff;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background-color: #f0f7ff;
  display: flex;
  align-items: center;
  justify-content: center;
}

.popup-option span {
  font-size: var(--font-size-sm);
  color: #333;
}

.popup-cancel {
  padding: 16px;
  text-align: center;
  font-size: var(--font-size-md);
  background-color: #fafafa;
  color: #333;
  border-top: 1px solid #f0f0f0;
  cursor: pointer;
}

.popup-cancel:active {
  background-color: #f0f0f0;
}

/* Hover效果（非触摸设备） */
@media (hover: hover) {
  .upload-actions i:hover {
    color: rgba(0, 0, 0, 0.8);
  }
  
  .popup-option:hover i {
    background-color: #e6f7ff;
  }
  
  .popup-cancel:hover {
    background-color: #f5f5f5;
  }
}

/* 触摸反馈效果 */
@media (hover: none) {
  .upload-trigger:active {
    background-color: #f0f0f0;
  }
  
  .popup-option:active i {
    background-color: #e6f7ff;
    transform: scale(0.95);
  }
}
</style> 